#ifndef DATABASE_AOF_H
#define DATABASE_AOF_H

#include "../base/FileUtil.hpp"

#include <functional>
#include <string>

namespace DBServer
{
namespace Database
{

class Aof {
public:
    using AofRwFunc = std::function<void(Base::Unti::UnlockAppendFile&)>;
    Aof(AofRwFunc log_func, int aof_write_buff_size, std::string aof_file = AOF_FILE);
    ~Aof();

    // when the db start,
    // read the db.aof to resume the data
    void pseudo_client();

    // save the command to aof_buf
    // only save the motified command
    // such as SET and DEL
    void save(std::string);

private:
    // flush the aof_buf per second
    void flush();

    // when db.aof's size arrive a specified size
    // fork a process to rewrite a base.aof
    // and parent process append to incr.aof
    // finally append the incr.aof to base.aof
    // and rename the base.aof to db.aof
    // then aof rewrite is finish
    void aof_rw();

    // child process begin translate incr.aof to 
    // base.aof, so parent process need write the operation
    // to the aof buf. when chile process make a finish signal
    // indicate that the aof rewrite is finish,
    // parent process can flush the aof buffer to db.aof
    // at this process, parent close the db.aof first, open
    // and write to incr.aof, then, close incr.aof after
    // access the siganl which child begin to translate
    // finally, when aof rewrite finish,
    // parent restart the db.aof flush the aof buffer to db.aof
    // while child process already remove the base.aof and incr.aof
    // and replace db.aof atomically.
    void begin();

    // aof finish
    void end();


    void child_aof_rw();

    void parent_aof_rw_second_stage();
    void parent_aof_rw_third_stage_begin();
    void parent_aof_rw_third_stage_end();

private:
    char *aof_buf;                          // for aof buf
    int off_set;                            // buf offset

    int is_begin_aof_translate;             // disable flush or not
    int is_begin_aof_rw;       
    int signal[2];                          // singal pipe
    AofRwFunc aof_func;                     // child scan the dict function

    Base::Unti::ReadFile aof_reader; // read aof file : db.aof incr.aof base.aof

    Base::Unti::FileStat aof;

    int aof_fd; // when it is not doing aof rewrite
                // aof_fd -> db.aof
                // in parent process -> incr.aof
                // in device process -> base.aof

    int buff_size;
    Base::Unti::UnlockAppendFile aof_writer;
    // write aof file : db.aof incr.aof base.aof
    //
    // when datebase begin aof rewrite
    // aof_write will open a new file which is called incr.aof
    // and close the db.aof, because db.aof will be replaced by
    // base.aof.

};

} // namespace Database
} // namespace DBServer


#endif